home *** CD-ROM | disk | FTP | other *** search
Wrap
/* graphics libraries: transfer mode library by Cary Clark, Georgiann Delaney, Michael Fairman, Dave Good, Josh Horwich, Robert Johnson, Keith McGreggor, Oliver Steele, David Van Brink, Chris Yerga Copyright 1987 - 1993 Apple Computer, Inc. All rights reserved. */ #include <Memory.h> #include "graphics libraries.h" /* * Routines */ static void InitColorMatrix(Fixed m[5][4]) { register Fixed *x; register short i; x = &m[0][0]; for(i = 19; i>=0; i--) *x++ = 0; m[0][0] = m[1][1] = m[2][2] = m[3][3] = fixed1; /* Identity matrix, for cleanliness */ } /* * Initialize all fields of a transfermode record * to a very reasonable rgb copy mode. */ void InitTransferMode(gxTransferMode *mode) { NilParamReturn(mode); SetCommonTransfer(mode,gxCopyMode,0,nil); } gxTransferMode *SetCommonTransfer(register gxTransferMode *mode, commonTransferMode type, unsigned short opValue, const gxColor *opColor) { register gxTransferComponent *component; register short i; gxColor oColor; NilParamReturnNil(mode); if(opColor) { oColor = *opColor; GXConvertColor(&oColor,gxRGBASpace, nil, nil); } else { oColor.space = gxRGBASpace; oColor.element.rgba.red = oColor.element.rgba.green = oColor.element.rgba.blue = opValue; oColor.element.rgba.alpha = 65535; } if(type >= gxOverMode && type <= gxFadeMode) mode->space = gxRGBASpace; else mode->space = gxRGBSpace; mode->flags = 0; mode->set = nil; mode->profile = nil; component = &mode->component[0]; InitColorMatrix(mode->sourceMatrix); InitColorMatrix(mode->deviceMatrix); InitColorMatrix(mode->resultMatrix); component->mode = type; component->flags = 0; component->sourceMinimum = component->deviceMinimum = component->clampMinimum = 0; component->sourceMaximum = component->deviceMaximum = component->clampMaximum = 65535; for(i = 3; i>=0; i--) { component = &mode->component[i]; *component = mode->component[0]; component->operand = (&oColor.element.rgb.red)[i]; switch(type) { case gxHighlightMode: if(!opColor) /* if no opColor passed, use lomem RGBHilite */ component->operand = ((short *)0xDA0)[i]; break; case gxOverMode: /* use it like a real alpha mode */ if(i==3) component->mode = gxRampOrMode; break; case gxAtopMode: /* use it like a real alpha mode */ if(i==3) { component->flags |= gxReverseComponent; component->mode = gxCopyMode; /* result alpha = device alpha */ } break; case gxExcludeMode: /* use it like a real alpha mode */ if(i==3) component->mode = gxRampXorMode; break; case gxFadeMode: if(i==3) component->mode = gxAddMode; break; case commonAddOverMode: component->mode = gxAddMode; component->flags |= gxOverResultComponent; break; case commonSubtractOverMode: component->mode = gxAddMode; component->flags |= gxOverResultComponent; mode->sourceMatrix[i][i] = -fixed1; break; case commonSubtractPinMode: component->mode = gxAddMode; mode->sourceMatrix[i][i] = -fixed1; break; case commonTransparentMode: /* the opColor specifies which gxColor to avoid from source */ component->mode = gxCopyMode; mode->flags |= gxRejectSourceTransfer; if(opColor) { component->sourceMinimum = component->sourceMaximum = (&oColor.element.rgb.red)[i]; } else /* default is avoid drawing white */ { component->sourceMinimum = component->sourceMaximum = 65535; } break; case commonInMode: if(i==3) component->mode = gxRampAndMode; else component->mode = gxCopyMode; break; case commonOutMode: if(i==3) { component->mode = gxRampAndMode; mode->deviceMatrix[3][3] = -fixed1; mode->deviceMatrix[4][3] = 65535; } else component->mode = gxCopyMode; break; } } return mode; } void SetInkCommonTransfer(gxInk source, commonTransferMode type) { gxTransferMode mode; NilInkReturn(source); SetCommonTransfer(&mode, type,32768,nil); GXSetInkTransfer(source, &mode); } void SetShapeCommonTransfer(gxShape source, commonTransferMode type) { gxTransferMode mode; NilShapeReturn(source); SetCommonTransfer(&mode, type,32768,nil); GXSetShapeTransfer(source, &mode); } commonTransferMode GetShapeCommonTransfer(gxShape source) { gxTransferMode mode; NilShapeReturnNil(source); GXGetShapeTransfer(source, &mode); return mode.component[0].mode; } commonTransferMode GetInkCommonTransfer(gxInk source) { gxTransferMode mode; NilInkReturnNil(source); GXGetInkTransfer(source, &mode); return mode.component[0].mode; } gxColor *TransmogrifyColor(gxColor *dstColor, const gxColor *srcColor, const gxTransferMode *mode) { gxInk tempInk = GXNewInk(); GXSetInkColor(tempInk,srcColor); GXSetInkTransfer(tempInk,mode); GXCombineColor(dstColor, tempInk); GXDisposeInk(tempInk); return dstColor; } /* Given an gxInk and a device, set's up the gxInk's mode so that drawing over the background gxColor leaves * the result gxColor. Also sets up the gxTransferMode gxColorSpace etc. so that the fast case is taken. */ void SetInkFastXorTransfer(gxInk inky, gxViewDevice destDevice, gxViewPort destViewPort, gxColor *background, gxColor *result) { gxShape deviceBitsShape; gxBitmap deviceBits; gxTransferMode fastMode; gxColor inkColor; gxColor localBackground; gxColor localResult; localBackground.space = gxRGBSpace; localBackground.profile = nil; localBackground.element.rgb.red = 0xFFFF; localBackground.element.rgb.green = 0xFFFF; localBackground.element.rgb.blue = 0xFFFF; localResult.space = gxRGBSpace; localResult.profile = nil; localResult.element.rgb.red = 0; localResult.element.rgb.green = 0; localResult.element.rgb.blue = 0; if (background) localBackground = *background; if (result) localResult = *result; deviceBitsShape = GXGetViewDeviceBitmap(destDevice); GXGetBitmap(deviceBitsShape, &deviceBits, nil); if (destViewPort && (GXGetViewPortAttributes(destViewPort) & gxEnableMatchPort) == 0) { localBackground.profile = deviceBits.profile; /* if drawing through the viewport will disable color matching, we */ localResult.profile = deviceBits.profile; /* want to do the same thing for our GXConvertColor calls. */ } InitTransferMode(&fastMode); fastMode.flags |= gxSingleComponentTransfer; fastMode.component[0].mode = gxXorMode; if ((fastMode.space = deviceBits.space) == gxIndexedSpace) { fastMode.set = deviceBits.set; GXConvertColor(&localBackground, gxIndexedSpace, deviceBits.set, deviceBits.profile); GXConvertColor(&localResult, gxIndexedSpace, deviceBits.set, deviceBits.profile); if (localBackground.element.indexed.index == localResult.element.indexed.index) { /* OK, the two colors map into the same index. We will instead use black and white */ localBackground.space = gxRGBSpace; localBackground.profile = nil; localBackground.element.rgb.red = 0xFFFF; localBackground.element.rgb.green = 0xFFFF; localBackground.element.rgb.blue = 0xFFFF; localResult.space = gxRGBSpace; localResult.profile = nil; localResult.element.rgb.red = 0; localResult.element.rgb.green = 0; localResult.element.rgb.blue = 0; GXConvertColor(&localBackground, gxIndexedSpace, deviceBits.set, deviceBits.profile); GXConvertColor(&localResult, gxIndexedSpace, deviceBits.set, deviceBits.profile); if (localBackground.element.indexed.index == localResult.element.indexed.index) { if (localResult.element.indexed.index > 1) --localResult.element.indexed.index; else ++localResult.element.indexed.index; /* This assumes that gxColorSet has at least 2 colors */ } } inkColor.space = gxIndexedSpace; inkColor.profile = deviceBits.profile; inkColor.element.indexed.set = deviceBits.set; inkColor.element.indexed.index = ((localBackground.element.indexed.index - 1) ^ (localResult.element.indexed.index - 1)) + 1; } else { fastMode.space = gxRGBSpace; GXConvertColor(&localBackground, gxRGBSpace, nil, deviceBits.profile); GXConvertColor(&localResult, gxRGBSpace, nil, deviceBits.profile); inkColor.space = gxRGBSpace; inkColor.profile = deviceBits.profile; inkColor.element.rgb.red = localBackground.element.rgb.red ^ localResult.element.rgb.red; inkColor.element.rgb.green = localBackground.element.rgb.green ^ localResult.element.rgb.green; inkColor.element.rgb.blue = localBackground.element.rgb.blue ^ localResult.element.rgb.blue; } GXSetInkColor(inky, &inkColor); GXSetInkTransfer(inky, &fastMode); GXDisposeShape(deviceBitsShape); } void SetShapeFastXorTransfer(gxShape source, gxColor *background, gxColor *result) { long viewPortCount; viewPortCount = GXGetTransformViewPorts(GXGetShapeTransform(source), nil); if( viewPortCount ) { gxViewPort vp; gxViewDevice vd; gxInk inky; long viewDeviceCount; void *buffer = NewPtr( sizeof(gxViewPort) * viewPortCount ); if (MemError()) Debugger(); GXGetTransformViewPorts(GXGetShapeTransform(source), (gxViewPort *)buffer); if( viewDeviceCount = GXGetViewPortViewDevices(vp = *(gxViewPort *)buffer, nil) ) { SetPtrSize((Ptr) buffer, viewDeviceCount * sizeof(gxViewDevice)); if (MemError()) { DisposePtr((Ptr) buffer); buffer = NewPtr(viewDeviceCount * sizeof(gxViewDevice)); if (MemError()) Debugger(); } GXGetViewPortViewDevices(vp, (gxViewDevice *)buffer); vd = *(gxViewDevice *)buffer; if (GXGetInkOwners(inky = GXGetShapeInk(source)) > 1) { GXSetShapeInk(source, inky = GXNewInk()); GXDisposeInk(inky); } SetInkFastXorTransfer(inky, vd, vp, background, result); GXSetShapeInkAttributes(source, GXGetShapeInkAttributes(source) | gxSuppressDitherInk); } DisposePtr((Ptr) buffer); } }